<template>
  <div class="departments-container">
    <div class="app-container">
      <!-- 卡片组件 -->
      <el-card class="tree-card">
        <!-- 用了一个行列布局
          type flex布局
          justify 水平对齐方式
          align 垂直的对齐方式 -->
        <!-- 头部公司的tree-tools -->
        <tree-tools
          :node-data="company"
          :is-root="true"
          @add-depts="handleAddDepts"
        />
        <!--
          tree组件 data指的是对象数组
          props 修改映射，因为后端的字段不一定是label和children
          default-expand-all 是否默认展开所有 默认值false 默认不展开
          完整写法 :default-expand-all="true"
          default-expand-all与上述完整写法等价
         -->
        <el-tree :data="departs" :props="defaultProps" default-expand-all>
          <!--
            主要用的是data字段，node字段仅作了解，双大括号语法会报错
            data 当前节点的数据-对象类型
          -->
          <template #default="{data}">
            <!-- {{ data.name }} - {{ data.manager }} -->
            <!-- 非头部 一级部门二级部门... -->
            <!-- isRoot父传子 默认值就是false 所以可以不写 -->
            <tree-tools
              :node-data="data"
              :is-root="false"
              @del-depts="getDepartments"
              @add-depts="handleAddDepts"
              @edit-depts="handleEditDepts"
            />
          </template>
        </el-tree>
      </el-card>
    </div>
    <!--
      @update:dialogVisible="dialogVisible = $event"

      几个语法糖如果考你了 也是比较基础的
      v-model - :value @input
      .sync - @update:xxx = 'xxx = $event'
     -->
    <add-dept
      ref="addDeptRef"
      :dialog-visible.sync="dialogVisible"
      :node-data="nodeData"
      :depts="depts"
      @add-depts="getDepartments"
    />
  </div>

</template>

<script>
import { tranListToTreeData } from '@/utils'
import TreeTools from './components/tree-tools.vue'
import { reqGetDepartments } from '@/api/departments'
import AddDept from './components/add-dept.vue'
export default {
  name: 'Departments',
  components: { TreeTools, AddDept },
  data() {
    return {
      /**
       * 树状数据 对象数组 核心就2个字段
       *   label - 节点的名称 字符串
       *   children - 孩子节点们 对象数组
       *
       */
      dialogVisible: false,
      company: {},
      departs: [],
      defaultProps: {
        // children: 'children',
        label: 'name'
      },
      nodeData: {},
      depts: []

    }
  },
  async created() {
    // 发送请求，获取部门列表
    // 由于我们获取部门列表 应该是要多次调用 ？（为什么要多次调用 - 新增修改删除需要刷新列表）
    // 所以我们需要封装一个函数，方便多次调用
    this.getDepartments()
  },
  methods: {
    /**
     * 1. 子传父 不一样的组件 起的一样的事件名 会有影响吗
     *    不会有影响，组件是互相独立的，恰巧事件名起的一样
     * 2. 为什么下面2个方法一样不复用
     *    给大家科普了open事件 - 每次打开弹层都会触发，发送请求
     *    原先的需求，其实只在created调用了一次，新增编辑打开目前都不会调用
     *    但编辑的需求，希望拿到最新的数据，所以我们编辑的时候希望调用获取员工简单列表
     *    强调这个是我们人资的业务需求，具体需求以后大家根据工作定
     */
    handleEditDepts(nodeData) {
      this.dialogVisible = true
      this.nodeData = nodeData
      // 之后的回显需求，需要调用请求，会拿到更详细的数据，而不用nodeData
      // 调用获取简单员工列表数据 - 如何调用另外个组件的方法
      // 大致参考的方案 就类似我们form实例的方法调用 this.$refs.xxx.validate
      // 通过设置ref属性，可以拿到对应组件的实例，这样实例上的方法数据都能拿到
      const addDeptRef = this.$refs.addDeptRef
      addDeptRef.getEmployeeSimple()
      // 获取详情
      addDeptRef.getDepartDetail(nodeData.id)
      // addDeptRef.getDepartDetail()
    },
    handleAddDepts(nodeData) {
      // console.log(nodeData)
      this.dialogVisible = true
      this.nodeData = nodeData
    },
    closeDialogFn(flag) {
      // console.log('儿子传给父亲的参数', flag)
      this.dialogVisible = flag
    },
    async getDepartments() {
      const { data: { depts, companyName }} = await reqGetDepartments()
      this.company = {
        name: companyName,
        manager: '负责人',
        id: '' // id为空的原因 其实一级部门的pid为空
      }
      // console.log(JSON.parse(JSON.stringify(depts)))
      // 列表数据易于遍历寻找对应的项，我们在自定义校验要用，接收数据后父传子传给add-dept
      this.depts = depts
      /**
       * 为什么要用递归处理树状结构
       * 一级部门 -> 二级部门 -> 三级部门 -> ....
       * 本质上就是不断找一个部门的孩子 - 找孩子是类似的逻辑
       * 递归 - 自己调用自己
       *
       * 细节 filter item.pid === xxx 获取孩子部门
       * 如果一个部门没有孩子，那我们这样的逻辑处理后获取的是空数组
       *
       * pid 空的时候 才是一级部门 - 后端返回的数据观察得出的结论
       *
       * pid "6051ad90e93db6522c1d00d2" 这个是技术部的id
       * 所以我们如果传入这个作为标识的flag 获取的是技术部的孩子
       * pid "604e2251b205b95968e1312c" 财务部的id
       * 方法返回的是财务部的孩子
       * pid "604e2297b205b95968e1312f" 税务部的id
       * 因为税务部没有孩子，那他返回的是空数组
       */
      this.departs = tranListToTreeData(depts, '')
    }

  }
}
</script>

<style scoped lang="scss">
.tree-card {
  padding: 30px 30px;
  font-size:14px;
}
.el-tree {
  ::v-deep {
    // 小三角的样式, 去掉默认的小三角的旋转效果
    .el-tree-node__expand-icon.expanded {
      -webkit-transform: rotate(0deg);
      transform: rotate(0deg);
    }
    // 有子节点 且未展开 +
    .el-icon-caret-right:before {
      background: url("~@/assets/common/add-circle.png") no-repeat 0 0;
      content: '';
      display: block;
      width: 16px;
      height: 16px;
      font-size: 16px;
      background-size: 16px;
    }
    // 有子节点 且已展开 -
    .el-tree-node__expand-icon.expanded.el-icon-caret-right:before{
      background: url("~@/assets/common/minus-circle.png") no-repeat 0 0;
      content: '';
      display: block;
      width: 16px;
      height: 16px;
      font-size: 16px;
      background-size: 16px;
    }
    // 没有子节点
    .el-tree-node__expand-icon.is-leaf::before  {
      background: url("~@/assets/common/user-filling.png") no-repeat 0 0;
      content: '';
      display: block;
      width: 16px;
      height: 16px;
      font-size: 16px;
      background-size: 16px;
    }
  }
}
</style>
